/**
 * @description 防抖函数，只执行规定时间内触发的最后一次
 * @param {() => void} fn 要执行的回调函数
 * @param {number} duration 延迟执行的时间，默认500毫秒
 * @return () => void
 */
export function debounce<A extends any[], R>(
    fn: (...args: A) => R,
    duration: number = 500
): (...args: A) => void {
    let timer: ReturnType<typeof setTimeout> | null = null;

    return function (this: any, ...args: A) {
        if (timer) {
            clearTimeout(timer);
            timer = null;
        }

        timer = setTimeout(() => {
            fn.apply(this, args);
        }, duration);
    };
}

/**
 * @description 判断数组中是否存在某个值
 * @param {Array<T>} list 目标数组
 * @param {keyof T | ((item: T) => any)} key 收集数据的key
 * @return [Set<number | string>, (target: any) => boolean]
 */
export const createCheckoutKey = <T>(
    list: Array<T>,
    key: keyof T | ((item: T) => any)
): [Set<number | string>, (target: any) => boolean] => {
    const set: Set<number | string> = new Set();
    const handler = typeof key === 'function' ? key : (item: T) => item[key];

    for (let i = 0; i < list.length; i++) {
        const id = handler(list[i]);
        set.add(id);
    }

    return [set, (target: any) => set.has(target)];
};

/**
 * @description 生成uuid
 * @return string
 */
export const createUUID = (): string => {
    if (crypto && crypto.randomUUID) {
        return crypto.randomUUID();
    }

    return Date.now() + Math.random().toString(32);
};
